﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JeuDeDames;

namespace JeuDeDames
{
    public class Damier
    {
        public const int BLANC = -1;
        public const int NOIR = 1;
        public const int PROFONDEUR = 2;

        public Joueur j1;
        public Joueur j2;
        public static Case[] damier = new Case[144];
        public static int nbTour;
        public static List<Coup> historiqueCoups; /*correspond au nombre de tour de la partie*/

        public Damier() { }

        public Damier(Joueur J1, Joueur J2, String annonce)
        {
            Console.Clear();
            Console.WriteLine("\t\t- Vous êtes en zone de Test -\n");

            j1 = J1;
            j2 = J2;
            historiqueCoups = new List<Coup>();
            //damier = new Case[144];
            int i = 0;
            int j = 0;

            /*-----INITIALISATION DE DAMIER A VIDE------*/
            /*premiere ligne du tableau*/
            for (i = 0; i < 12; i++)
            {
                damier[i] = new CaseBord(i);
            }
            /*On remplit 2 lignes à la fois. j controle qu'on a fini une ligne pour sauter une ligne.*/
            while (i < 132)
            {
                if (j < 12)
                {
                    /*Si sur la premiere ligne la case i est un bord*/
                    if (i % 12 == 0 || i % 12 == 11)
                    {
                        damier[i] = new CaseBord(i);
                        damier[i + 12] = new CaseBord(i + 12);
                    }
                    /*Si sur la premiere ligne la case i est une case blanche*/
                    else if (i % 12 == 1 || i % 12 == 3 || i % 12 == 5 || i % 12 == 7 || i % 12 == 9)
                    {
                        /*2ème lignes des pions noirs. Ces pions ne sont pas mobiles.*/
                        if (i > 12 && i < 23)
                        {
                            damier[i + 12] = new CaseNoire(i + 12);
                        }
                        /*4ème lignes des pions noirs. Ces pions sont mobiles.*/
                        else if (i > 36 && i < 47)
                        {
                            damier[i + 12] = new CaseNoire(i + 12);
                        }
                        /*3ème ligne et */
                        else if (i > 84 && i < 119)
                        {
                            damier[i + 12] = new CaseNoire(i + 12);
                        }
                        else
                            damier[i + 12] = new CaseNoire(i + 12);
                        damier[i] = new CaseBlanche(i);
                    }
                    /*Si sur la premiere ligne la case i est une case noire*/
                    else if (i % 12 == 2 || i % 12 == 4 || i % 12 == 6 || i % 12 == 8 || i % 12 == 10)
                    {
                        if (i > 12 && i < 47)
                        {
                            damier[i] = new CaseNoire(i);
                        }
                        else if (i > 84 && i < 95)
                        {
                            damier[i] = new CaseNoire(i);
                        }
                        else if (i > 108 && i < 131)
                        {
                            damier[i] = new CaseNoire(i);
                        }
                        else
                            damier[i] = new CaseNoire(i);
                        damier[i + 12] = new CaseBlanche(i + 12);
                    }
                    i++;
                    j++;
                }
                /*On a terminé la premiere ligne, donc on saute une ligne en avançant i de 12*/
                else
                {
                    i += 12;
                    j = 0;
                }
            }
            /*derniere ligne du tableau*/
            for (i = 131; i < 144; i++)
            {
                damier[i] = new CaseBord(i);
            }
        }

        public Damier(Joueur J1, Joueur J2) //(Blancs, Noirs)
        {
            j1 = J1;
            j2 = J2;
            historiqueCoups = new List<Coup>();
            //damier = new Case[144];
            int i = 0;
            int j = 0;
            /*-----INITIALISATION DE DAMIER------*/
            /*premiere ligne du tableau*/
            for (i = 0; i < 12; i++)
            {
                damier[i] = new CaseBord(i);
            }
            /*On remplit 2 lignes à la fois. j controle qu'on a fini une ligne pour sauter une ligne.*/
            while (i < 132)
            {
                if (j < 12)
                {
                    /*Si sur la premiere ligne la case i est un bord*/
                    if (i % 12 == 0 || i % 12 == 11)
                    {
                        damier[i] = new CaseBord(i);
                        damier[i + 12] = new CaseBord(i + 12);
                    }
                    /*Si sur la premiere ligne la case i est une case blanche*/
                    else if (i % 12 == 1 || i % 12 == 3 || i % 12 == 5 || i % 12 == 7 || i % 12 == 9)
                    {
                        /*2ème lignes des pions noirs. Ces pions ne sont pas mobiles.*/
                        if (i > 12 && i < 23)
                        {
                            Piece unPion = new Pion(i + 12, j2);
                            damier[i + 12] = new CaseNoire(i + 12, unPion);
                            j2.lesPieces.Add(unPion);
                        }
                        /*4ème lignes des pions noirs. Ces pions sont mobiles.*/
                        else if (i > 36 && i < 47)
                        {
                            Piece unPion = new Pion(i + 12, j2);
                            damier[i + 12] = new CaseNoire(i + 12, unPion);
                            j2.lesPieces.Add(unPion);
                        }
                        /*3ème ligne et */
                        else if (i > 84 && i < 119)
                        {
                            Piece unPion = new Pion(i + 12, j1);
                            damier[i + 12] = new CaseNoire(i + 12, unPion);
                            j1.lesPieces.Add(unPion);
                        }
                        else
                            damier[i + 12] = new CaseNoire(i + 12);
                        damier[i] = new CaseBlanche(i);
                    }
                    /*Si sur la premiere ligne la case i est une case noire*/
                    else if (i % 12 == 2 || i % 12 == 4 || i % 12 == 6 || i % 12 == 8 || i % 12 == 10)
                    {
                        if (i > 12 && i < 47)
                        {
                            Piece unPion = new Pion(i, j2);
                            damier[i] = new CaseNoire(i, unPion);
                            j2.lesPieces.Add(unPion);
                        }
                        else if (i > 84 && i < 95)
                        {
                            Piece unPion = new Pion(i, j1, true);
                            damier[i] = new CaseNoire(i, unPion);
                            j1.lesPieces.Add(unPion);
                            //j1.piecesMobiles.Add(damier[i].piece);
                        }
                        else if (i > 108 && i < 131)
                        {
                            Piece unPion = new Pion(i, j1);
                            damier[i] = new CaseNoire(i, unPion);
                            j1.lesPieces.Add(unPion);
                        }
                        else
                            damier[i] = new CaseNoire(i);
                        damier[i + 12] = new CaseBlanche(i + 12);
                    }
                    i++;
                    j++;
                }
                /*On a terminé la premiere ligne, donc on saute une ligne en avançant i de 12*/
                else
                {
                    i += 12;
                    j = 0;
                }
            }
            /*derniere ligne du tableau*/
            for (i = 131; i < 144; i++)
            {
                damier[i] = new CaseBord(i);
            }
        }

        public void partie()
        {
            /*Tant qu'on peut jouer*/
            while (finPartie() == false)
            {

            }
        }

        public void changerTour()
        {
            bool temp = j1.monTour;
            j1.monTour = j2.monTour;
            j2.monTour = temp;
        }

        public void jouerUnTour()
        {
            //int pmax = 2;
            Coup coup = null;
            if (j1.monTour == true)
            {
                Console.WriteLine("C'est au tour de "+this.j1.nom+" :"); 
                if (j1 is Humain)
                {
                    j1.calculCoupsPossibles(this);
                    j1.afficheCoupsPossibles();
                    coup = (j1 as Humain).coupAJouer();   //utilisateur rentre ses coordonnées. Celles-ci doivent correspondre à un coup présent dans la liste coupPossible
                }
                else if (j1 is Ordinateur)
                {
                    (j1 as Ordinateur).minmax(this, j2, 0, ref coup);
                    //(j1 as Ordinateur).minMax(this, j1, pmax, ref coup, pmax);
                }
                j1.jouer(coup, this);
                
            }
            else if (j2.monTour == true)
            {
                Console.WriteLine("C'est au tour de "+this.j2.nom+" :");
                if (j2 is Humain)
                {
                    j2.calculCoupsPossibles(this);
                    j2.afficheCoupsPossibles();
                    coup = (j2 as Humain).coupAJouer();   //utilisateur rentre ses coordonnées. Celles-ci doivent correspondre à un coup présent dans la liste coupPossible
                }
                else if (j2 is Ordinateur)
                {
                    (j2 as Ordinateur).minmax(this, j1, 0, ref coup);
                    //(j2 as Ordinateur).minMax(this, j2, pmax, ref coup, pmax);
                    Console.WriteLine(coup);
                }
                j2.jouer(coup, this);

            }
            changerTour();
        }

        public void afficheDamier()
        {
            Console.Clear();
            Console.WriteLine("\t\tTour numéro "+((nbTour+2)/2)+"\n");
            Console.WriteLine("      A   B   C   D   E   F   G   H   I   J    ");
            Console.WriteLine("     ___ ___ ___ ___ ___ ___ ___ ___ ___ ___   ");
            int i = 13;
            string ligne;
            for (int j = 0; j < 10; j++)
            {
                if (j < 9)
                    ligne = (j + 1) + " ";
                else
                    ligne = (j + 1) + "";
                if (j == 2)
                {
                    Console.WriteLine(" " + ligne + " | " + damier[i].ToString() + " | " + damier[i + 1].ToString() + " | " + damier[i + 2].ToString() + " | " + damier[i + 3].ToString() + " | " + damier[i + 4].ToString() + " | " + damier[i + 5].ToString() + " | " + damier[i + 6].ToString() + " | " + damier[i + 7].ToString() + " | " + damier[i + 8].ToString() + " | " + damier[i + 9].ToString() + " |  "+ligne+"  " + j2.nom + " " + j2.lesPieces.Count);
                    Console.WriteLine("    |___|___|___|___|___|___|___|___|___|___|  ");
                }
                else if (j == 7)
                {
                    Console.WriteLine(" " + ligne + " | " + damier[i].ToString() + " | " + damier[i + 1].ToString() + " | " + damier[i + 2].ToString() + " | " + damier[i + 3].ToString() + " | " + damier[i + 4].ToString() + " | " + damier[i + 5].ToString() + " | " + damier[i + 6].ToString() + " | " + damier[i + 7].ToString() + " | " + damier[i + 8].ToString() + " | " + damier[i + 9].ToString() + " |  "+ligne+"  " + j1.nom + " " + j1.lesPieces.Count);
                    Console.WriteLine("    |___|___|___|___|___|___|___|___|___|___|  ");
                }
                else
                {
                    Console.WriteLine(" " + ligne + " | " + damier[i].ToString() + " | " + damier[i + 1].ToString() + " | " + damier[i + 2].ToString() + " | " + damier[i + 3].ToString() + " | " + damier[i + 4].ToString() + " | " + damier[i + 5].ToString() + " | " + damier[i + 6].ToString() + " | " + damier[i + 7].ToString() + " | " + damier[i + 8].ToString() + " | " + damier[i + 9].ToString() + " |  "+ligne);
                    Console.WriteLine("    |___|___|___|___|___|___|___|___|___|___|  ");
                }
                i += 12;
            }
            Console.WriteLine("\n      A   B   C   D   E   F   G   H   I   J    ");
            
        }

        public bool finPartie()
        {
            /*Cas où le joueur 1 ou 2 n'a plus de pièces*/
            if ((j1.lesPieces.Count == 0) || (j2.lesPieces.Count == 0))
                return true;
            else
                return false;
        }

        public void annulerTour(int tour)
        {
              List<Coup> newHistorique = new List<Coup>();
              historiqueCoups.Reverse();
            foreach(Coup unCoup in historiqueCoups)
            {
                if (unCoup.nbTour == tour)
                {
                    annulerCoup(unCoup);
                }
                else
                {
                    newHistorique.Add(unCoup);
            }
            }
            nbTour--;
            changerTour();
            historiqueCoups = newHistorique;
        }

        public void annulerCoup(Coup unCoup)
        {
            if (unCoup.piece == null)
            {
                annulerDeplacement(unCoup);
            }
            else
            {
                annulerMangage(unCoup);
            }
        }

        public void annulerMangage(Coup unCoup)
        {
            (Damier.damier[unCoup.piece.position] as CaseNoire).piece = unCoup.piece;
            unCoup.piece.joueur.lesPieces.Add(unCoup.piece);
            unCoup.origine.piece = unCoup.destination.piece;
            unCoup.origine.piece.position = unCoup.origine.position;
            unCoup.destination.piece = null;
        }

        public void annulerDeplacement(Coup unCoup)
        {
            unCoup.origine.piece = unCoup.destination.piece;
            unCoup.destination.piece = null;
            unCoup.origine.piece.position = unCoup.origine.position;
        }

        public Damier dupliquerDamier()
        {
            Damier unDamier = new Damier();
            unDamier.MemberwiseClone();
            return unDamier;
        }

        public Damier menu(ref bool isMenuTest)
        {
            int choix = 0;
            do
            {
                try
                {
                    Console.Clear();
                    Console.WriteLine("\t\tProjet Jeu de Dames !\n");
                    Console.WriteLine("Choix du type de jeu");
                    Console.WriteLine("\t1- Humain vs Machine");
                    Console.WriteLine("\t2- Humain vs Humain");
                    Console.WriteLine("\t3- Machine vs Humain");
                    Console.WriteLine("\t4- Machine vs Machine (le choc des titans !)");
                    Console.WriteLine("\t5- Zone de test (attention chantier !)\n");
                    Console.Write("Entrez le numéro correspondant à votre choix : ");
                    string caseChoisi = Console.ReadLine();
                    choix = int.Parse(caseChoisi);
                    switch (choix)
                    {
                        case 1:
                            return new Damier(new Humain(BLANC, "Humain"), new Ordinateur(NOIR));
                        case 2:
                            return new Damier(new Humain(BLANC, "Blanc"), new Humain(NOIR, "Noirs"));
                        case 3:
                            return new Damier(new Ordinateur(BLANC), new Humain(NOIR, "Humain"));
                        case 4:
                            return new Damier(new Ordinateur(BLANC), new Ordinateur(NOIR));
                        case 5:
                            isMenuTest = true;
                            return menuZoneTest();

                        default:
                            choix = 0;
                            break;
                    }
                }
                catch (System.FormatException) { choix = 0; }
            } while (choix == 0);
            return null;
        }

        //------------------------------------------------------------------------------MENU ZONE TEST ----------------------------------------------->
        public Damier menuZoneTest()
        {
            int choixTypeJeu = 0;
            int choixTypePlateau = 0;

            do
            {
                try
                {
                    Console.Clear();
                    Console.WriteLine(" \t\t- Zone de test -\n ");
                    Console.WriteLine("Choix du type de jeu:");
                    Console.WriteLine("\t1- Humain vs Machine");
                    Console.WriteLine("\t2- Humain vs Humain");
                    Console.WriteLine("\t3- Machine vs Machine\n");
                    Console.Write("Entrez le numéro correspondant à votre choix : ");
                    string caseChoisi = Console.ReadLine();
                    choixTypeJeu = int.Parse(caseChoisi);
                    switch (choixTypeJeu)
                    {
                        //HUMAIN VS IA
                        case 1:
                            do
                            {
                                try
                                {
                                    Console.WriteLine("\nChoix du type de Plateau:");
                                    Console.WriteLine("\t1- Plateau personnalisé");
                                    Console.WriteLine("\t2- Plateau parmis une situation de damier\n");
                                    Console.Write("Entrez le numéro correspondant à votre choix : ");
                                    string caseChoisi1 = Console.ReadLine();
                                    choixTypePlateau = int.Parse(caseChoisi1);
                                    switch (choixTypePlateau)
                                    {
                                        case 1:
                                            return new Damier(new Humain(BLANC, "testeur blanc"), new Ordinateur(NOIR), "zone de test J VS IA");
                                        case 2:
                                            // isMenuSituationTest = true;
                                            return menuSituationTest();

                                        default:
                                            choixTypePlateau = 0;
                                            break;
                                    }
                                }
                                catch (System.FormatException) { choixTypePlateau = 0; }
                            } while (choixTypePlateau == 0);
                            return null;

                        //HUMAIN VS HUMAIN   /!\ DEMANDE PRéALABLE IDéE VINC
                        case 2:
                            do
                            {
                                try
                                {
                                    Console.WriteLine("\nChoix du type de Plateau:");
                                    Console.WriteLine("\t1- Plateau personnalisé");
                                    Console.WriteLine("\t2- Plateau parmis une situation de damier\n");
                                    Console.Write("Entrez le numéro correspondant à votre choix : ");
                                    string caseChoisi2 = Console.ReadLine();
                                    choixTypePlateau = int.Parse(caseChoisi2);
                                    switch (choixTypePlateau)
                                    {
                                        case 1:
                                            //Demander choix aux testeur / permet de voir si blanc et noir réagissent de la même manière dans chaque couleur (vinc) 
                                            return new Damier(new Humain(BLANC, "testeur blanc"), new Humain(NOIR, "testeur noir"), "zone de test J VS J");
                                        case 2:
                                            //isMenuSituationTest = true;
                                            return menuSituationTest();

                                        default:
                                            choixTypePlateau = 0;
                                            break;
                                    }
                                }
                                catch (System.FormatException) { choixTypePlateau = 0; }
                            } while (choixTypePlateau == 0);
                            return null;

                        //MACHINE VS MACHINE
                        case 3:
                            do
                            {
                                try
                                {
                                    //CHOIX DE PROFONDEUR DE L'IA
                                    bool verif = false;
                                    int choixProfBlanc = 0;
                                    int choixProfNoir = 0;

                                    while (verif == false)
                                    {
                                        try
                                        {
                                            Console.WriteLine("\nChoix de la profondeur de l'IA Blanc:");
                                            choixProfBlanc = int.Parse(Console.ReadLine());
                                        }
                                        catch (FormatException) { }
                                        if (choixProfBlanc != 0)
                                        {
                                            verif = true;
                                        }
                                    }

                                    verif = false;

                                    while (verif == false)
                                    {
                                        try
                                        {
                                            Console.WriteLine("\nChoix de la profondeur de l'IA Noir:");
                                            choixProfNoir = int.Parse(Console.ReadLine());
                                        }
                                        catch (FormatException) { }
                                        if (choixProfNoir != 0)
                                        {
                                            verif = true;
                                        }
                                    }

                                    Console.WriteLine("\nChoix du type de Plateau:");
                                    Console.WriteLine("\t1- Plateau personnalisé");
                                    Console.WriteLine("\t2- Plateau parmis une situation de damier\n");
                                    Console.WriteLine("Entrez le numéro correspondant à votre choix : ");
                                    string caseChoisi3 = Console.ReadLine();
                                    choixTypePlateau = int.Parse(caseChoisi3);
                                    switch (choixTypePlateau)
                                    {
                                        case 1:
                                            return new Damier(new Ordinateur(BLANC, choixProfBlanc), new Ordinateur(NOIR, choixProfNoir), "zone de test IA VS IA");
                                        case 2:
                                            //isMenuSituationTest = true;
                                            return menuSituationTest();

                                        default:
                                            choixTypePlateau = 0;
                                            break;
                                    }
                                }
                                catch (System.FormatException) { choixTypePlateau = 0; }
                            } while (choixTypePlateau == 0);
                            return null;

                        default:
                            choixTypeJeu = 0;
                            break;
                    }
                }
                catch (System.FormatException) { choixTypeJeu = 0; }
            } while (choixTypeJeu == 0);
            return null;
        }

        //------------------------------------------------------------------------------MENU SITUATION PRECONFIG ------------------------------------->
        // partie de seb, choisir des damiers prédéfinies
        public Damier menuSituationTest()
        {
            int choix = 0;
            do
            {
                try
                {
                    Console.Clear();
                    Console.WriteLine("\nChoix du type de Situation:");
                    Console.WriteLine("\t1- La Banane\n ");
                    Console.WriteLine("Entrez le numéro correspondant à votre choix : ");
                    string caseChoisi = Console.ReadLine();
                    choix = int.Parse(caseChoisi);
                    switch (choix)
                    {
                        case 1:
                            Joueur j1 = new Humain(BLANC, "patrick");
                            Joueur j2 = new Humain(NOIR, "banana");

                            this.j1 = j1;
                            this.j2 = j2;

                            Piece unPion = new Pion(14, this.j1);
                            this.j1.lesPieces.Add(unPion);
                            Damier.damier[unPion.position] = new CaseNoire(unPion.position, unPion);

                            Piece unPion1 = new Pion(114, this.j2);
                            this.j2.lesPieces.Add(unPion1);
                            Damier.damier[unPion1.position] = new CaseNoire(unPion1.position, unPion1);
                            afficheDamier();
                            return new Damier(j1, j2, "testposition 1");


                    }
                }
                catch (System.FormatException) { choix = 0; }
            } while (choix == 0);
            return null;
        }
    }
}